import { HTMLStencilElement } from '@stencil/core/internal';
import { OverlayInterface } from '../../interface';

export const createOverlay = <T extends HTMLStencilElement>(
  tagName: string,
  props?: Record<string, unknown>,
): Promise<T> => {
  if (typeof customElements !== 'undefined') {
    return customElements.whenDefined(tagName).then(() => {
      const element = document.createElement(tagName) as HTMLStencilElement;
      element.classList.add('os-hidden');

      // convert the passed in overlay options into props
      // that get passed down into the new overlay
      Object.assign(element, props);

      // append the overlay element to the document body
      getAppRoot(document).appendChild(element);

      return element.componentOnReady() as any;
    });
  }
  return Promise.resolve() as any;
};

export const present = async (overlay: OverlayInterface) => {
  if (overlay.presented) {
    return;
  }
  overlay.presented = true;

  if (overlay.keyboardClose) {
    overlay.el.focus();
  }
};

export const dismiss = async (overlay: OverlayInterface, data: any | undefined): Promise<boolean> => {
  if (!overlay.presented) {
    return false;
  }
  overlay.presented = false;
  try {
    // Overlay contents should not be clickable during dismiss
    overlay.el.style.setProperty('pointer-events', 'none');
    overlay.didDismiss.emit(data);
  } catch (err) {
    console.error(err);
  }

  overlay.el.remove();
  return true;
};

const getAppRoot = (doc: Document) => {
  return doc.body;
};

export const eventMethod = <T>(element: HTMLElement, eventName: string): Promise<T> => {
  let resolve: (detail: T) => void;
  const promise = new Promise<T>(r => (resolve = r));
  onceEvent(element, eventName, (event: any) => {
    resolve(event.detail);
  });
  return promise;
};

export const onceEvent = (element: HTMLElement, eventName: string, callback: (ev: Event) => void) => {
  const handler = (ev: Event) => {
    element.removeEventListener(eventName, handler);
    callback(ev);
  };
  element.addEventListener(eventName, handler);
};
